package demo1;

import java.util.Scanner;

/**
 * 模拟单道操作系统，管理进程的创建、运行、阻塞和终止。
 */
public class OS {
    // 操作系统运行状态：true表示运行，false表示停止
    private boolean isRun;
    // 就绪队列、执行队列和阻塞队列
    private final PCBQueue readyQueue;
    private final PCBQueue runningQueue;
    private final PCBQueue blockQueue;
    // 内存管理对象
    private final Memory memory;
    // 键盘输入
    private final Scanner scanner;

    /**
     * 构造函数，初始化操作系统。
     */
    public OS() {
        // 初始化三个队列
        this.readyQueue = new PCBQueue("就绪队列", 10);
        this.runningQueue = new PCBQueue("执行队列", 1); // 执行队列容量为1（单道系统）
        this.blockQueue = new PCBQueue("阻塞队列", 10);

        this.scanner = new Scanner(System.in);
        System.out.println("请输入内存基址和大小：");
        int baseAddr = scanner.nextInt();
        int capacity = scanner.nextInt();
        this.memory = new Memory(baseAddr, capacity);
        this.isRun = true;
    }

    /**
     * 运行操作系统，提供交互界面。
     */
    public void run() {
        System.out.println("进程管理系统运行中：输入 H(help) 查看命令列表");
        while (isRun) {
            System.out.println("******************************");
            System.out.print("->");
            String command = scanner.next().toUpperCase(); // 读取命令并转为大写
            switch (command) {
                case "Q":
                    isRun = false; // 退出系统
                    break;
                case "H":
                    help(); // 显示帮助信息
                    break;
                case "C":
                    creat(); // 创建进程
                    break;
                case "T":
                    terminate(); // 终止进程
                    break;
                case "E":
                    end(); // 时间片结束
                    break;
                case "B":
                    block(); // 阻塞进程
                    break;
                case "W":
                    wake(); // 唤醒进程
                    break;
                case "S":
                    show(); // 显示状态
                    break;
                default:
                    System.out.println("无效命令，请重新输入!");
                    break;
            }
        }
    }

    /**
     * 创建新进程并尝试分配内存。
     */
    private void creat() {
        System.out.println("请输入新进程的名字与大小(空格隔开)：");
        String processId = scanner.next();
        int memorySize;
        try {
            memorySize = scanner.nextInt();
            if (memorySize <= 0) {
                System.out.println("错误：内存大小必须为正数！");
                return;
            }
        } catch (Exception e) {
            System.out.println("错误：请输入有效的内存大小（整数）！");
            scanner.nextLine(); // 清除无效输入
            return;
        }

        PCB pcb = new PCB(processId, memorySize);
        if (memory.add(pcb)) { // 分配内存成功
            System.out.println("进程 " + pcb.getId() +
                    " 创建成功，基地址=" + pcb.getBaseAddr() +
                    ", 内存大小=" + pcb.getLength());
            readyQueue.offer(pcb); // 加入就绪队列
            if (runningQueue.isEmpty() && !readyQueue.isEmpty()) {
                PCB nextPCB = readyQueue.remove();
                runningQueue.offer(nextPCB);
                System.out.println("进程 " + nextPCB.getId() + " 已进入执行队列");
            }
        } else {
            System.out.println("进程 " + pcb.getId() + " 创建失败：内存不足！");
        }
    }

    /**
     * 阻塞当前运行的进程。
     */
    private void block() {
        PCB pcb = runningQueue.remove(); // 移除执行队列中的进程
        if (pcb != null) {
            blockQueue.offer(pcb); // 加入阻塞队列
        }
        if (readyQueue.isEmpty()) {
            System.out.println("就绪队列为空");
        } else {
            runningQueue.offer(readyQueue.remove()); // 从就绪队列取进程执行
        }
    }

    /**
     * 唤醒阻塞队列中的进程。
     */
    private void wake() {
        if (blockQueue.isEmpty()) {
            System.out.println("阻塞队列为空");
        } else {
            readyQueue.offer(blockQueue.remove()); // 从阻塞队列取进程到就绪队列
        }
        if (runningQueue.isEmpty() && !readyQueue.isEmpty()) {
            runningQueue.offer(readyQueue.remove()); // 从就绪队列取进程执行
        }
    }

    /**
     * 时间片结束，将运行进程放回就绪队列。
     */
    private void end() {
        PCB pcb = runningQueue.remove(); // 移除执行队列中的进程
        if (pcb != null) {
            readyQueue.offer(pcb); // 放回就绪队列尾部
        }
        if (!readyQueue.isEmpty()) {
            runningQueue.offer(readyQueue.remove()); // 从就绪队列取进程执行
        }
    }

    /**
     * 终止当前运行的进程。
     */
    private void terminate() {
        if (runningQueue.isEmpty()) {
            System.out.println("执行态为空");
        } else {
            PCB pcb = runningQueue.remove(); // 移除执行队列中的进程
            if (pcb != null && memory.remove(pcb)) { // 从内存中移除
                if (!readyQueue.isEmpty()) {
                    runningQueue.offer(readyQueue.remove()); // 从就绪队列取进程执行
                }
            }
        }
    }

    /**
     * 显示各队列和内存的状态。
     */
    private void show() {
        readyQueue.show(); // 显示就绪队列
        runningQueue.show(); // 显示执行队列
        blockQueue.show(); // 显示阻塞队列
        memory.show(); // 显示内存状态
    }

    /**
     * 显示帮助信息，列出可用命令。
     */
    private void help() {
        System.out.println("查看队列：S (show：查看各队列情况以及剩余内存)");
        System.out.println("创建进程：C (create：创建一个新进程加入就绪队列尾)");
        System.out.println("终止进程：T (terminate：终止处于执行队列的进程)");
        System.out.println("时间片到：E (end：将执行进程放入就绪队列尾，将就绪队列头加入执行队列)");
        System.out.println("阻塞进程：B (block：阻塞执行进程，加入阻塞队列)");
        System.out.println("唤醒进程：W (wake：唤醒阻塞队列队首进程，加入就绪队列尾)");
        System.out.println("退出程序：Q (quit)");
    }

    /**
     * 主方法，启动操作系统。
     */
    public static void main(String[] args) {
        OS os = new OS();
        os.run();
    }

    // Getter和Setter方法
    public boolean isRun() {
        return isRun;
    }

    public void setRun(boolean run) {
        isRun = run;
    }

    public PCBQueue getReadyQueue() {
        return readyQueue;
    }

    public PCBQueue getRunningQueue() {
        return runningQueue;
    }

    public PCBQueue getBlockQueue() {
        return blockQueue;
    }

    public Memory getMemory() {
        return memory;
    }
}